#include "PlayGameScene.h"
#include "defines.h"
#include <stdlib.h>
#include "ShowWinnerScene.h"
#include "LevelManager.h"
#include "LevelData.h"

PlayGameScene::~PlayGameScene()
{
	CC_SAFE_RELEASE_NULL(_layer);	
}

bool PlayGameScene::init()
{
	if ( CCScene::init() )
	{
		this->_layer = PlayGameLayer::create();
		if (! _layer) return false;
		this->_layer->retain();
		this->addChild(_layer);
		// add gameLoop function
		this->schedule(schedule_selector(PlayGameScene::gameLoop));

		return true;
	}
	
	return false;
}

void PlayGameScene::gameLoop(float time)
{
	
}

bool PlayGameLayer::init()
{
	bool result = false;
	do
	{
		// load level
		LevelManager::GetInstance()->LoadLevel();

		this->m_iRows = LevelManager::GetInstance()->GetLevel(0)->m_iRow;
		this->m_iColumns = LevelManager::GetInstance()->GetLevel(0)->m_iColumn;
		for (int i = 0;i < m_iRows;i++)
		{
			vector<int> rows;
			vector<GameObject*> objects;
			for (int j = 0;j < m_iColumns;j++)
			{
				rows.push_back(LevelManager::GetInstance()->GetLevel(0)->m_LevelMatrix[i][j]);
				objects.push_back(NULL);
			}
			m_pLevelMatrix.push_back(rows);
			m_pObjectMatrix.push_back(objects);
		}

		CC_BREAK_IF(! CCLayerColor::initWithColor(ccc4(255, 255, 255, 255)));
		CCSize size = CCDirector::sharedDirector()->getWinSize();

		// add background
		GameSprite* background = GameSprite::gameSpriteWithFile("background.jpg");
		CC_BREAK_IF(!background);
		background->setPosition(ccp(size.width / 2, size.height / 2));
		this->addChild(background);
		
		m_pTileMap = CCTMXTiledMap::create("TileMap.tmx");
		m_pTileMapBackground = m_pTileMap->layerNamed("TableLayer");

		CC_BREAK_IF(!m_pTileMap);
		CC_BREAK_IF(!m_pTileMapBackground);

		// Place the sprite on the center of the screen
		m_pTileMap->setAnchorPoint(ccp(0.5f, 0.5f));
		m_pTileMap->setPosition(ccp(size.width / 2, size.height / 2));		

		// add puzzle background
		GameSprite* puzzleBackground = GameSprite::gameSpriteWithFile("puzzleBackground.jpg");
		CC_BREAK_IF(!puzzleBackground);
		puzzleBackground->setPosition(ccp(size.width / 2, size.height / 2));
		puzzleBackground->setAnchorPoint(ccp(.5f, .5f));	
		puzzleBackground->setScale(0.7f);
		this->addChild(puzzleBackground);

		// add left bar background
		GameSprite* leftbarBackground = GameSprite::gameSpriteWithFile("leftBarBackground.png");
		CC_BREAK_IF(!leftbarBackground);
		leftbarBackground->setPosition(ccp(0, 0));
		leftbarBackground->setAnchorPoint(ccp(0, 0));
		this->addChild(leftbarBackground);
		
		// add button
		float xLeftButtonStart = 15.0f;
		float yLeftButtonStart = 45.0f;
		GameSprite* button = GameSprite::gameSpriteWithFile("button4.png");
		CC_BREAK_IF(!button);
		button->setPosition(ccp(xLeftButtonStart, yLeftButtonStart));
		button->setAnchorPoint(ccp(0, 0));
		this->addChild(button);

		yLeftButtonStart = 164;
		button = GameSprite::gameSpriteWithFile("button3.png");
		CC_BREAK_IF(!button);
		button->setPosition(ccp(xLeftButtonStart, yLeftButtonStart));
		button->setAnchorPoint(ccp(0, 0));
		this->addChild(button);

		yLeftButtonStart = 273;
		button = GameSprite::gameSpriteWithFile("button2.png");
		CC_BREAK_IF(!button);
		button->setPosition(ccp(xLeftButtonStart, yLeftButtonStart));
		button->setAnchorPoint(ccp(0, 0));
		this->addChild(button);

		yLeftButtonStart = 383;
		button = GameSprite::gameSpriteWithFile("button1.png");
		CC_BREAK_IF(!button);
		button->setPosition(ccp(xLeftButtonStart, yLeftButtonStart));
		button->setAnchorPoint(ccp(0, 0));
		this->addChild(button);

		GameSprite* sprite = GameSprite::gameSpriteWithFile("levelText.png");
		CC_BREAK_IF(!sprite);
		sprite->setPosition(ccp(xLeftButtonStart, 528));
		sprite->setAnchorPoint(ccp(0, 0));
		this->addChild(sprite);

		// Add the sprite to HelloWorld layer as a child layer.
		this->addChild(m_pTileMap, 0);			

		CC_BREAK_IF(!addObjectToScene());
		this->setTouchEnabled(true);

		result = true;
	}
	while(0);

	return result;          
}

bool PlayGameLayer::addObjectToScene()
{	
	float startX = m_pTileMap->getPositionX() - m_pTileMap->getContentSize().width / 2 + m_pTileMap->getContentSize().width / 6;
	float startY = m_pTileMap->getPositionY() + m_pTileMap->getContentSize().height / 2 - m_pTileMap->getContentSize().height / 6;
	float width = m_pTileMap->getContentSize().width / 3;
	float height = m_pTileMap->getContentSize().height / 3;
	float x,y;
	for (int i = 0;i < 3 ;i++)
	{
		for (int j = 0;j < 3;j++)
		{
			GameObject* go = 0;

			x = j * width + startX;			
			y = startY - i * height;

			switch(m_pLevelMatrix[i][j])
			{
			case BT_POINTER:
				if (!m_pPointer)
				{
					m_pPointer = new GameObject();					
					if (!m_pPointer->initObject("pointer.png", this, x, y, i, j, BT_POINTER))
						return false;

					m_pObjectMatrix[i][j] = m_pPointer;
				}									
				break;

			case BT_RED_LEFT:
				go = new GameObject();
				if (!go->initObject("red_left.png", this, x, y, i, j, BT_RED_LEFT))
					return false;				
				break;

			case BT_RED_RIGHT:
				go = new GameObject();
				if (!go->initObject("red_right.png", this, x, y, i, j, BT_RED_RIGHT))
					return false;			
				break;

			case BT_RED_UP:
				go = new GameObject();		
				if (!go->initObject("red_up.png", this, x, y, i, j, BT_RED_UP))
					return false;				
				break;

			case BT_RED_DOWN:
				go = new GameObject();				
				if (!go->initObject("red_down.png", this, x, y, i, j, BT_RED_DOWN))
					return false;				
				break;

			case BT_BLUE_LEFT:
				go = new GameObject();			
				if (!go->initObject("blue_left.png", this, x, y, i, j, BT_BLUE_LEFT))
					return false;				
				break;

			case BT_BLUE_RIGHT:
				go = new GameObject();			
				if (!go->initObject("blue_right.png", this, x, y, i, j, BT_BLUE_RIGHT))
					return false;				
				break;

			case BT_BLUE_UP:
				go = new GameObject();
				if (!go->initObject("blue_up.png", this, x, y, i, j, BT_BLUE_UP))
					return false;			
				break;

			case BT_BLUE_DOWN:
				go = new GameObject();
				if (!go->initObject("blue_down.png", this, x, y, i, j, BT_BLUE_DOWN))
					return false;				
				break;

			case BT_SMALLBLACK_LEFT:
				go = new GameObject();
				if (!go->initObject("small_black_left.png", this, x, y, i, j, BT_SMALLBLACK_LEFT))
					return false;				
				break;

			case BT_SMALLBLACK_RIGHT:
				go = new GameObject();
				if (!go->initObject("small_black_right.png", this, x, y, i, j, BT_SMALLBLACK_RIGHT))
					return false;				
				break;

			case BT_SMALLBLACK_UP:
				go = new GameObject();
				if (!go->initObject("small_black_up.png", this, x, y, i, j, BT_SMALLBLACK_UP))
					return false;				
				break;

			case BT_SMALLBLACK_DOWN:
				go = new GameObject();
				if (!go->initObject("small_black_down.png", this, x, y, i, j, BT_SMALLBLACK_DOWN))
					return false;				
				break;

			case BT_BIGBLACK_LEFT:
				go = new GameObject();
				if (!go->initObject("big_black_left.png", this, x, y, i, j, BT_BIGBLACK_LEFT))
					return false;				
				break;

			case BT_BIGBLACK_RIGHT:
				go = new GameObject();
				if (!go->initObject("big_black_right.png", this, x, y, i, j, BT_BIGBLACK_RIGHT))
					return false;				
				break;

			case BT_BIGBLACK_UP:
				go = new GameObject();
				if (!go->initObject("big_black_up.png", this, x, y, i, j, BT_BIGBLACK_UP))
					return false;				
				break;

			case BT_BIGBLACK_DOWN:
				go = new GameObject();
				if (!go->initObject("big_black_down.png", this, x, y, i, j, BT_BIGBLACK_DOWN))
					return false;				
				break;

			case BT_WALL:
				go = new GameObject();
				if (!go->initObject("black_wall.png", this, x, y, i, j, BT_WALL))
					return false;				
				break;
				
			}	

			if (go)
				m_pObjectMatrix[i][j] = go;
		}
	}

	return true;
}

PlayGameLayer::PlayGameLayer() : m_pTileMap(NULL),
								m_pPointer(NULL)							
{
	/*m_iRows = m_iColumns = 3;
	for (int i = 0;i < m_iRows;i++)
	{
		vector<int> rows;
		vector<GameObject*> objects;
		for (int j = 0;j < m_iColumns;j++)
		{
			rows.push_back(0);
			objects.push_back(NULL);
		}
		m_pLevelMatrix.push_back(rows);
		m_pObjectMatrix.push_back(objects);
	}
	
	m_pLevelMatrix[0][0] = BT_NONE;
	m_pLevelMatrix[0][1] = BT_NONE;
	m_pLevelMatrix[0][2] = BT_NONE;
	m_pLevelMatrix[1][0] = BT_RED_UP;
	m_pLevelMatrix[1][1] = BT_POINTER;
	m_pLevelMatrix[1][2] = BT_BLUE_LEFT;
	m_pLevelMatrix[2][0] = BT_NONE;	
	m_pLevelMatrix[2][1] = BT_NONE;
	m_pLevelMatrix[2][2] = BT_NONE;*/
}

PlayGameLayer::~PlayGameLayer()
{	
	for (int i = 0; i < m_iRows; i++)
	{
		for (int j = 0; j < m_iColumns; j++)
		{
			/*if (m_pObjectMatrix[i][j] != NULL)
			{
				m_pObjectMatrix[i][j]->release();
				m_pObjectMatrix[i][j] = NULL;
			}*/

			CC_SAFE_RELEASE_NULL(m_pObjectMatrix[i][j]);
		}
	}
}

void PlayGameLayer::ccTouchesEnded(cocos2d::CCSet* touches, cocos2d::CCEvent* event)
{
	for ( CCSetIterator i = touches->begin(); i != touches->end(); i++)
	{
		CCTouch *touch = (CCTouch*)(*i);
		if (touch)
		{
			CCPoint tap = touch->getLocation();
			if (m_pPointer->getTouch() && m_pPointer->getTouch() == touch)
			{				
				int row = m_pPointer->getRow();
				int column = m_pPointer->getColumn();
				int width = m_pTileMap->getContentSize().width / m_iColumns;
				int height = m_pTileMap->getContentSize().height / m_iRows;
				float startX = m_pTileMap->getPositionX() - m_pTileMap->getContentSize().width / 2;
				float startY = m_pTileMap->getPositionY() - m_pTileMap->getContentSize().height / 2;
				float xLimitLeft = startX + column * width;
				float xLimitRight = xLimitLeft + width;				
				float yLimitBottom = startY + (m_iRows - 1 - row) * height;
				float yLimitTop = yLimitBottom + height;				
				float currentX = xLimitLeft + width / 2;
				float currentY = yLimitBottom + height / 2;

				MoveType_e eMoveType = MT_NONE;
				GameObject* go = m_pPointer->m_pAttachGameObject;
				while(go)
				{
					if (!go->m_pAttachGameObject)	break;
					go = go->m_pAttachGameObject;
				}

				if (abs(tap.x - currentX) > abs(tap.y - currentY) + 5)
				{
					tap.y = currentY;

					if (tap.x > currentX + width / 2)
						eMoveType = MT_RIGHT;
					else if ( tap.x < currentX - width / 2)
						eMoveType = MT_LEFT;

					if (eMoveType == MT_RIGHT)
					{
						if (go)
						{
							while(go->m_eObjectType == BT_RED_RIGHT || go->m_eObjectType == BT_BLUE_RIGHT
								|| go->m_eObjectType == BT_SMALLBLACK_RIGHT || go->m_eObjectType == BT_BIGBLACK_RIGHT)
							{
								if (!go->m_pParentGameObject) break;
								go = go->m_pParentGameObject;
							}
						}

						GameObject* nextObj = m_pObjectMatrix[row][column + 1];

						if (nextObj && go && (go->m_eObjectType == BT_RED_DOWN || go->m_eObjectType == BT_RED_UP
							|| go->m_eObjectType == BT_RED_LEFT || go->m_eObjectType == BT_RED_RIGHT) && nextObj->m_eObjectType == BT_BLUE_LEFT)
						{
							this->GoToScene();
							return ;
						}

						if (go)	
						{
							m_pObjectMatrix[row][column] = go->m_pAttachGameObject;
							if (go->m_pAttachGameObject)
							{
								go->m_pAttachGameObject->setPosition(currentX, currentY);
								go->m_pAttachGameObject->m_pParentGameObject = NULL;
							}
							go->m_pAttachGameObject = nextObj;	

							if (nextObj)
								nextObj->m_pParentGameObject = go;
						}
						else
						{
							m_pObjectMatrix[row][column] = m_pPointer->m_pAttachGameObject;
							if (m_pPointer->m_pAttachGameObject)
							{
								m_pPointer->m_pAttachGameObject->setPosition(currentX, currentY);
								m_pPointer->m_pAttachGameObject->m_pParentGameObject = NULL;
							}
							m_pPointer->m_pAttachGameObject = nextObj;
							if (nextObj)
								nextObj->m_pParentGameObject = m_pPointer;
						}

						m_pPointer->setColumn(column + 1);
						m_pObjectMatrix[row][column + 1] = m_pPointer;
						tap.x = startX + (column + 1) * width + width / 2;
					}
					else if (eMoveType == MT_LEFT)
					{
						if (go)
						{
							while(go->m_eObjectType == BT_RED_LEFT || go->m_eObjectType == BT_BLUE_LEFT
								|| go->m_eObjectType == BT_SMALLBLACK_LEFT || go->m_eObjectType == BT_BIGBLACK_LEFT)
							{
								if (!go->m_pParentGameObject) break;
								go = go->m_pParentGameObject;
							}
						}

						GameObject* previousObj = m_pObjectMatrix[row][column - 1];

						if (previousObj && go && (go->m_eObjectType == BT_RED_DOWN || go->m_eObjectType == BT_RED_UP
							|| go->m_eObjectType == BT_RED_LEFT || go->m_eObjectType == BT_RED_RIGHT) && previousObj->m_eObjectType == BT_BLUE_RIGHT)
						{
							this->GoToScene();
							return ;
						}

						if (go)	
						{
							m_pObjectMatrix[row][column] = go->m_pAttachGameObject;
							if (go->m_pAttachGameObject)
							{
								go->m_pAttachGameObject->setPosition(currentX, currentY);
								go->m_pAttachGameObject->m_pParentGameObject = NULL;
							}
							go->m_pAttachGameObject = previousObj;	

							if (previousObj)
								previousObj->m_pParentGameObject = go;
						}
						else
						{
							m_pObjectMatrix[row][column] = m_pPointer->m_pAttachGameObject;
							if (m_pPointer->m_pAttachGameObject)
							{
								m_pPointer->m_pAttachGameObject->setPosition(currentX, currentY);
								m_pPointer->m_pAttachGameObject->m_pParentGameObject = NULL;
							}
							m_pPointer->m_pAttachGameObject = previousObj;
							if (previousObj)
								previousObj->m_pParentGameObject = m_pPointer;
						}

						m_pPointer->setColumn(column - 1);
						m_pObjectMatrix[row][column - 1] = m_pPointer;
						tap.x = startX + (column - 1) * width + width / 2;
					}
					else
					{
						tap.x = currentX;
						tap.y = currentY;
					}
				}
				else if (abs(tap.x - currentX ) + 5 < abs(tap.y - currentY))
				{
					tap.x = currentX;

					if (tap.y > currentY + height / 2)
						eMoveType = MT_UP;
					else if (tap.y < currentY - height / 2)
						eMoveType = MT_DOWN;

					if (eMoveType == MT_UP)
					{

						if (go)
						{
							while(go->m_eObjectType == BT_RED_UP || go->m_eObjectType == BT_BLUE_UP
								|| go->m_eObjectType == BT_SMALLBLACK_UP || go->m_eObjectType == BT_BIGBLACK_UP)
							{
								if (!go->m_pParentGameObject) break;
								go = go->m_pParentGameObject;
							}
						}

						GameObject* previousObj = m_pObjectMatrix[row - 1][column];

						if (previousObj && go && (go->m_eObjectType == BT_RED_DOWN || go->m_eObjectType == BT_RED_UP
							|| go->m_eObjectType == BT_RED_LEFT || go->m_eObjectType == BT_RED_RIGHT) && previousObj->m_eObjectType == BT_BLUE_DOWN)
						{
							this->GoToScene();
							return ;
						}

						if (go)	
						{
							m_pObjectMatrix[row][column] = go->m_pAttachGameObject;
							if (go->m_pAttachGameObject)
							{
								go->m_pAttachGameObject->setPosition(currentX, currentY);
								go->m_pAttachGameObject->m_pParentGameObject = NULL;
							}
							go->m_pAttachGameObject = previousObj;	

							if (previousObj)
								previousObj->m_pParentGameObject = go;
						}
						else
						{
							m_pObjectMatrix[row][column] = m_pPointer->m_pAttachGameObject;
							if (m_pPointer->m_pAttachGameObject)
							{
								m_pPointer->m_pAttachGameObject->setPosition(currentX, currentY);
								m_pPointer->m_pAttachGameObject->m_pParentGameObject = NULL;
							}
							m_pPointer->m_pAttachGameObject = previousObj;
							if (previousObj)
								previousObj->m_pParentGameObject = m_pPointer;
						}

						m_pPointer->setRow(row - 1);
						m_pObjectMatrix[row - 1][column] = m_pPointer;
						tap.y = startY + (m_iRows - 1 - (row - 1)) * height + height / 2;
					}
					else if (eMoveType == MT_DOWN)
					{
						if (go)
						{
							while(go->m_eObjectType == BT_RED_DOWN || go->m_eObjectType == BT_BLUE_DOWN
								|| go->m_eObjectType == BT_SMALLBLACK_DOWN || go->m_eObjectType == BT_BIGBLACK_DOWN)
							{
								if (!go->m_pParentGameObject) break;
								go = go->m_pParentGameObject;
							}
						}

						GameObject* previousObj = m_pObjectMatrix[row + 1][column];

						if (previousObj && go && (go->m_eObjectType == BT_RED_DOWN || go->m_eObjectType == BT_RED_UP
							|| go->m_eObjectType == BT_RED_LEFT || go->m_eObjectType == BT_RED_RIGHT) && previousObj->m_eObjectType == BT_BLUE_UP)
						{
							this->GoToScene();
							return ;
						}

						if (go)	
						{
							m_pObjectMatrix[row][column] = go->m_pAttachGameObject;
							if (go->m_pAttachGameObject)
							{
								go->m_pAttachGameObject->setPosition(currentX, currentY);
								go->m_pAttachGameObject->m_pParentGameObject = NULL;
							}
							go->m_pAttachGameObject = previousObj;	

							if (previousObj)
								previousObj->m_pParentGameObject = go;
						}
						else
						{
							m_pObjectMatrix[row][column] = m_pPointer->m_pAttachGameObject;
							if (m_pPointer->m_pAttachGameObject)
							{
								m_pPointer->m_pAttachGameObject->setPosition(currentX, currentY);
								m_pPointer->m_pAttachGameObject->m_pParentGameObject = NULL;
							}
							m_pPointer->m_pAttachGameObject = previousObj;
							if (previousObj)
								previousObj->m_pParentGameObject = m_pPointer;
						}
												
						m_pPointer->setRow(row + 1);
						m_pObjectMatrix[row + 1][column] = m_pPointer;
						tap.y = startY + (m_iRows - 1 - (row + 1)) * height + height / 2;
					}
					else
					{
						tap.x = currentX;
						tap.y = currentY;
					}
				}
				else
				{
					tap.x = currentX;
					tap.y = currentY;
				}
				//m_pPointer->setPosition(tap.x, tap.y);
				Move(tap.x, tap.y, eMoveType);
				m_pPointer->setTouch(NULL);
			}
		}
	}
}

void PlayGameLayer::ccTouchesBegan(cocos2d::CCSet* touches, cocos2d::CCEvent* event)
{
	for ( CCSetIterator i = touches->begin(); i != touches->end(); i++)
	{
		CCTouch *touch = (CCTouch*) (*i);
		if (touch)
		{
			CCPoint tap = touch->getLocation();
			if (m_pPointer->isTouch(tap, touch))
				CCLog("object is touched ...");
		}
	}	
}

bool PlayGameLayer::allowMove(MoveType_e eMoveType)
{	
	int row = m_pPointer->getRow();
	int column = m_pPointer->getColumn();
	if (eMoveType == MT_LEFT)
	{					
		GameObject* obj = m_pObjectMatrix[row][column - 1];
		if (obj == NULL)
			return true;
		if (obj->m_eObjectType == BT_RED_RIGHT || obj->m_eObjectType == BT_BLUE_RIGHT 
			|| obj->m_eObjectType == BT_SMALLBLACK_RIGHT || obj->m_eObjectType == BT_BIGBLACK_RIGHT)
		{
			GameObject* attachGO = m_pPointer->m_pAttachGameObject;
			while(attachGO)
			{
				if (!attachGO->m_pAttachGameObject)		break;

				attachGO = attachGO->m_pAttachGameObject;
			}
			
			if (!attachGO) return true;

			while(attachGO->m_eObjectType == BT_RED_LEFT || attachGO->m_eObjectType == BT_BLUE_LEFT 
				|| attachGO->m_eObjectType == BT_BIGBLACK_LEFT || attachGO->m_eObjectType == BT_SMALLBLACK_LEFT)
			{
				if (!attachGO->m_pParentGameObject)	break;
				attachGO = attachGO->m_pParentGameObject;
			}

			if (attachGO->m_eObjectType == BT_POINTER && (obj->m_eObjectType == BT_BLUE_RIGHT || obj->m_eObjectType == BT_BIGBLACK_RIGHT))
				return true;

			if ((attachGO->m_eObjectType == BT_RED_DOWN || attachGO->m_eObjectType == BT_RED_UP
				|| attachGO->m_eObjectType == BT_RED_LEFT || attachGO->m_eObjectType == BT_RED_RIGHT) 
				&& (obj->m_eObjectType == BT_BLUE_RIGHT || obj->m_eObjectType == BT_BIGBLACK_RIGHT))

				return true;

			if ((attachGO->m_eObjectType == BT_SMALLBLACK_DOWN || attachGO->m_eObjectType == BT_SMALLBLACK_LEFT
				|| attachGO->m_eObjectType == BT_SMALLBLACK_RIGHT || attachGO->m_eObjectType == BT_SMALLBLACK_UP) 
				&& (obj->m_eObjectType == BT_BLUE_RIGHT || obj->m_eObjectType == BT_BIGBLACK_RIGHT))

				return true;
		}		
	}
	else if (eMoveType == MT_RIGHT)
	{
		GameObject* obj = m_pObjectMatrix[row][column + 1];
		if (!obj)		return true;

		if (obj->m_eObjectType == BT_RED_LEFT || obj->m_eObjectType == BT_BLUE_LEFT 
			|| obj->m_eObjectType == BT_SMALLBLACK_LEFT || obj->m_eObjectType == BT_BIGBLACK_LEFT)
		{
			GameObject* attachGO = m_pPointer->m_pAttachGameObject;
			while(attachGO)
			{
				if (!attachGO->m_pAttachGameObject)		break;

				attachGO = attachGO->m_pAttachGameObject;
			}
			
			if (!attachGO) return true;

			while(attachGO->m_eObjectType == BT_RED_RIGHT || attachGO->m_eObjectType == BT_BLUE_RIGHT 
				|| attachGO->m_eObjectType == BT_BIGBLACK_RIGHT || attachGO->m_eObjectType == BT_SMALLBLACK_RIGHT)
			{
				if (!attachGO->m_pParentGameObject)	break;
				attachGO = attachGO->m_pParentGameObject;
			}

			if (attachGO->m_eObjectType == BT_POINTER && (obj->m_eObjectType == BT_BLUE_LEFT || obj->m_eObjectType == BT_BIGBLACK_LEFT))
				return true;

			if ((attachGO->m_eObjectType == BT_RED_DOWN || attachGO->m_eObjectType == BT_RED_UP
				|| attachGO->m_eObjectType == BT_RED_LEFT || attachGO->m_eObjectType == BT_RED_RIGHT) 
				&& (obj->m_eObjectType == BT_BLUE_LEFT || obj->m_eObjectType == BT_BIGBLACK_LEFT))

				return true;

			if ((attachGO->m_eObjectType == BT_SMALLBLACK_DOWN || attachGO->m_eObjectType == BT_SMALLBLACK_LEFT
				|| attachGO->m_eObjectType == BT_SMALLBLACK_RIGHT || attachGO->m_eObjectType == BT_SMALLBLACK_UP) 
				&& (obj->m_eObjectType == BT_BLUE_LEFT || obj->m_eObjectType == BT_BIGBLACK_LEFT))

				return true;
		}		
	}
	else if (eMoveType == MT_UP)
	{
		GameObject* obj = m_pObjectMatrix[row - 1][column];
		if (!obj)		return true;

		if (obj->m_eObjectType == BT_RED_DOWN || obj->m_eObjectType == BT_BLUE_DOWN 
			|| obj->m_eObjectType == BT_SMALLBLACK_DOWN || obj->m_eObjectType == BT_BIGBLACK_DOWN)
		{
			GameObject* attachGO = m_pPointer->m_pAttachGameObject;
			while(attachGO)
			{
				if (!attachGO->m_pAttachGameObject)		break;

				attachGO = attachGO->m_pAttachGameObject;
			}
			
			if (!attachGO) return true;

			while(attachGO->m_eObjectType == BT_RED_UP || attachGO->m_eObjectType == BT_BLUE_UP 
				|| attachGO->m_eObjectType == BT_BIGBLACK_UP || attachGO->m_eObjectType == BT_SMALLBLACK_UP)
			{
				if (!attachGO->m_pParentGameObject)	break;
				attachGO = attachGO->m_pParentGameObject;
			}

			if (attachGO->m_eObjectType == BT_POINTER && (obj->m_eObjectType == BT_BLUE_DOWN || obj->m_eObjectType == BT_BIGBLACK_DOWN))
				return true;
			if ((attachGO->m_eObjectType == BT_RED_DOWN || attachGO->m_eObjectType == BT_RED_UP
				|| attachGO->m_eObjectType == BT_RED_LEFT || attachGO->m_eObjectType == BT_RED_RIGHT) 
				&& (obj->m_eObjectType == BT_BLUE_DOWN || obj->m_eObjectType == BT_BIGBLACK_DOWN))

				return true;

			if ((attachGO->m_eObjectType == BT_SMALLBLACK_DOWN || attachGO->m_eObjectType == BT_SMALLBLACK_LEFT
				|| attachGO->m_eObjectType == BT_SMALLBLACK_RIGHT || attachGO->m_eObjectType == BT_SMALLBLACK_UP) 
				&& (obj->m_eObjectType == BT_BLUE_DOWN || obj->m_eObjectType == BT_BIGBLACK_DOWN))

				return true;
		}	
	}
	else if (eMoveType == MT_DOWN)
	{
		GameObject* obj = m_pObjectMatrix[row + 1][column];
		if (!obj)		return true;

		if (obj->m_eObjectType == BT_RED_UP || obj->m_eObjectType == BT_BLUE_UP 
			|| obj->m_eObjectType == BT_SMALLBLACK_UP || obj->m_eObjectType == BT_BIGBLACK_UP)
		{
			GameObject* attachGO = m_pPointer->m_pAttachGameObject;
			while(attachGO)
			{
				if (!attachGO->m_pAttachGameObject)		break;

				attachGO = attachGO->m_pAttachGameObject;
			}
			
			if (!attachGO) return true;

			while(attachGO->m_eObjectType == BT_RED_DOWN || attachGO->m_eObjectType == BT_BLUE_DOWN 
				|| attachGO->m_eObjectType == BT_BIGBLACK_DOWN || attachGO->m_eObjectType == BT_SMALLBLACK_DOWN)
			{
				if (!attachGO->m_pParentGameObject)	break;
				attachGO = attachGO->m_pParentGameObject;
			}

			if (attachGO->m_eObjectType == BT_POINTER && (obj->m_eObjectType == BT_BLUE_UP || obj->m_eObjectType == BT_BIGBLACK_UP))
				return true;

			if ((attachGO->m_eObjectType == BT_RED_DOWN || attachGO->m_eObjectType == BT_RED_UP
				|| attachGO->m_eObjectType == BT_RED_LEFT || attachGO->m_eObjectType == BT_RED_RIGHT) 
				&& (obj->m_eObjectType == BT_BLUE_UP || obj->m_eObjectType == BT_BIGBLACK_UP))

				return true;

			if ((attachGO->m_eObjectType == BT_SMALLBLACK_DOWN || attachGO->m_eObjectType == BT_SMALLBLACK_LEFT
				|| attachGO->m_eObjectType == BT_SMALLBLACK_RIGHT || attachGO->m_eObjectType == BT_SMALLBLACK_UP) 
				&& (obj->m_eObjectType == BT_BLUE_UP || obj->m_eObjectType == BT_BIGBLACK_UP))

				return true;
		}	
	}

	return false;
}

void PlayGameLayer::ccTouchesMoved(cocos2d::CCSet* touches, cocos2d::CCEvent* event)
{
	CCLog("touch move ... ");
	for ( CCSetIterator i = touches->begin(); i != touches->end(); i++)
	{
		CCTouch *touch = (CCTouch*)(*i);
		if (touch)
		{
			CCPoint tap = touch->getLocation();
			if (!m_pPointer->getTouch())
			{
				m_pPointer->isTouch(tap, touch);
			}
			else if (m_pPointer->getTouch() && m_pPointer->getTouch() == touch)
			{				
				int row = m_pPointer->getRow();
				int column = m_pPointer->getColumn();
				int width = m_pTileMap->getContentSize().width / m_iColumns;
				int height = m_pTileMap->getContentSize().height / m_iRows;
				float startX = m_pTileMap->getPositionX() - m_pTileMap->getContentSize().width / 2;
				float startY = m_pTileMap->getPositionY() - m_pTileMap->getContentSize().height / 2;
				float xLimitLeft = startX + column * width;
				float xLimitRight = xLimitLeft + width;				
				float yLimitBottom = startY + (m_iRows - 1 - row) * height;
				float yLimitTop = yLimitBottom + height;				
				float currentX = xLimitLeft + width / 2;
				float currentY = yLimitBottom + height / 2;

				if (tap.x < startX)
					tap.x = startX;
				if (tap.x > startX + m_pTileMap->getContentSize().width)
					tap.x = startX + m_pTileMap->getContentSize().width;

				if (tap.y < startY)
					tap.y = startY;
				if (tap.y > startY + m_pTileMap->getContentSize().height)
					tap.y = startY + m_pTileMap->getContentSize().height;

				MoveType_e eMoveType = MT_NONE;
				if (abs(tap.x - currentX) > abs(tap.y - currentY) + 5)
				{					
					if (tap.x - currentX > 0)
						eMoveType = MT_RIGHT;
					else if (currentX - tap.x > 0)
						eMoveType = MT_LEFT;

					tap.y = currentY;

					if ((column == 0 && eMoveType == MT_LEFT) || (column == m_iColumns - 1 && eMoveType == MT_RIGHT))			// cannot move left or right
					{						
						tap.x = currentX;					
						m_pPointer->setTouch(NULL);
					}
					else 
					{															
						if (allowMove(eMoveType))
						{
							GameObject* go = m_pPointer->m_pAttachGameObject;
							while(go)
							{
								if (!go->m_pAttachGameObject)	break;
								go = go->m_pAttachGameObject;
							}

							if (eMoveType == MT_LEFT)			// move left
							{
								if (go)
								{								
									while(go->m_eObjectType == BT_RED_LEFT || go->m_eObjectType == BT_BLUE_LEFT
										|| go->m_eObjectType == BT_SMALLBLACK_LEFT || go->m_eObjectType == BT_BIGBLACK_LEFT)
									{
										if (!go->m_pParentGameObject) break;
										go = go->m_pParentGameObject;
									}
								}

								GameObject* previousObj = m_pObjectMatrix[row][column - 1];																
								if (tap.x <= xLimitLeft - width / 2)
								{			
									if (previousObj && go && (go->m_eObjectType == BT_RED_DOWN ||
										go->m_eObjectType == BT_RED_UP || go->m_eObjectType == BT_RED_LEFT ||
										go->m_eObjectType == BT_RED_RIGHT) 
										&& previousObj->m_eObjectType == BT_BLUE_RIGHT)
									{
										// win
										this->GoToScene();
										return ;
									}

									if (go)	
									{
										m_pObjectMatrix[row][column] = go->m_pAttachGameObject;
										if (go->m_pAttachGameObject)
										{
											go->m_pAttachGameObject->setPosition(currentX, currentY);
											go->m_pAttachGameObject->m_pParentGameObject = NULL;
										}
										go->m_pAttachGameObject = previousObj;	

										if (previousObj)
											previousObj->m_pParentGameObject = go;
									}
									else
									{
										m_pObjectMatrix[row][column] = m_pPointer->m_pAttachGameObject;
										if (m_pPointer->m_pAttachGameObject)
										{
											m_pPointer->m_pAttachGameObject->setPosition(currentX, currentY);
											m_pPointer->m_pAttachGameObject->m_pParentGameObject = NULL;
										}
										m_pPointer->m_pAttachGameObject = previousObj;
										if (previousObj)
											previousObj->m_pParentGameObject = m_pPointer;
									}

									m_pPointer->setColumn(column - 1);									
									m_pObjectMatrix[row][column - 1] = m_pPointer;
								}
							}
							else if (eMoveType == MT_RIGHT)			// move right
							{
								if (go)
								{
									while(go->m_eObjectType == BT_RED_RIGHT || go->m_eObjectType == BT_BLUE_RIGHT
										|| go->m_eObjectType == BT_SMALLBLACK_RIGHT || go->m_eObjectType == BT_BIGBLACK_RIGHT)
									{
										if (!go->m_pParentGameObject) break;
										go = go->m_pParentGameObject;
									}
								}

								GameObject* nextObj = m_pObjectMatrix[row][column + 1];								

								if (tap.x >= xLimitRight + width / 2)
								{
									if (nextObj && go && (go->m_eObjectType == BT_RED_DOWN || go->m_eObjectType == BT_RED_LEFT
										|| go->m_eObjectType == BT_RED_RIGHT || go->m_eObjectType == BT_RED_UP) 
										&& (nextObj->m_eObjectType == BT_BLUE_LEFT))
									{
										// win 
										this->GoToScene();
										return;
									}

									if (go)
									{
										m_pObjectMatrix[row][column] = go->m_pAttachGameObject;
										if (go->m_pAttachGameObject)
										{
											go->m_pAttachGameObject->setPosition(currentX, currentY);
											go->m_pAttachGameObject->m_pParentGameObject = NULL;
										}
										go->m_pAttachGameObject = nextObj;
										if (nextObj)
											nextObj->m_pParentGameObject = go;
									}
									else
									{
										m_pObjectMatrix[row][column] = m_pPointer->m_pAttachGameObject;
										if (m_pPointer->m_pAttachGameObject)
										{
											m_pPointer->m_pAttachGameObject->setPosition(currentX, currentY);
											m_pPointer->m_pAttachGameObject->m_pParentGameObject = NULL;
										}
										m_pPointer->m_pAttachGameObject = nextObj;

										if (nextObj)
											nextObj->m_pParentGameObject = m_pPointer;
									}

									m_pPointer->setColumn(column + 1);
									m_pObjectMatrix[row][column + 1] = m_pPointer;
								}
							}
						}
						else
						{
							tap.x = currentX;
							tap.y = currentY;
							m_pPointer->setTouch(NULL);
						}
					}						
				}
				else if (abs(tap.x - currentX ) + 5 < abs(tap.y - currentY))
				{										
					if (tap.y - currentY > 0)				
						eMoveType = MT_UP;			
					else if (currentY - tap.y > 0)					
						eMoveType = MT_DOWN;					

					tap.x = currentX;

					if ((row == 0 && eMoveType == MT_UP) || (row == m_iRows - 1 && eMoveType == MT_DOWN))			// cannot move up or down
					{
						tap.y = currentY;					
						m_pPointer->setTouch(NULL);
					}
					else 
					{															
						if (allowMove(eMoveType))
						{
							GameObject* go = m_pPointer->m_pAttachGameObject;
							while(go)
							{
								if (!go->m_pAttachGameObject)	break;
								go = go->m_pAttachGameObject;
							}

							if (eMoveType == MT_UP)			// move up
							{
								if (go)
								{
									while(go->m_eObjectType == BT_RED_UP || go->m_eObjectType == BT_BLUE_UP
										|| go->m_eObjectType == BT_SMALLBLACK_UP || go->m_eObjectType == BT_BIGBLACK_UP)
									{
										if (!go->m_pParentGameObject) break;
										go = go->m_pParentGameObject;
									}
								}

								GameObject* previousObj = m_pObjectMatrix[row - 1][column];																

								if (tap.y >= yLimitTop + height / 2)
								{
									if (previousObj && go && (go->m_eObjectType == BT_RED_DOWN ||
										go->m_eObjectType == BT_RED_UP || go->m_eObjectType == BT_RED_LEFT ||
										go->m_eObjectType == BT_RED_RIGHT) 
										&& previousObj->m_eObjectType == BT_BLUE_DOWN)
									{
										// win
										this->GoToScene();
										return ;
									}

									if (go)
									{
										m_pObjectMatrix[row][column] = go->m_pAttachGameObject;
										if (go->m_pAttachGameObject)
										{
											go->m_pAttachGameObject->setPosition(currentX, currentY);
											go->m_pAttachGameObject->m_pParentGameObject = NULL;
										}
										go->m_pAttachGameObject = previousObj;

										if (previousObj)
											previousObj->m_pParentGameObject = go;
									}
									else
									{
										m_pObjectMatrix[row][column] = m_pPointer->m_pAttachGameObject;
										if (m_pPointer->m_pAttachGameObject)
										{
											m_pPointer->m_pAttachGameObject->setPosition(currentX, currentY);
											m_pPointer->m_pAttachGameObject->m_pParentGameObject = NULL;
										}
										m_pPointer->m_pAttachGameObject = previousObj;

										if (previousObj)
											previousObj->m_pParentGameObject = m_pPointer;
									}

									m_pPointer->setRow(row - 1);														
									m_pObjectMatrix[row - 1][column] = m_pPointer;
								}
							}
							else if (eMoveType == MT_DOWN)
							{
								if (go)
								{								
									while(go->m_eObjectType == BT_RED_DOWN || go->m_eObjectType == BT_BLUE_DOWN
										|| go->m_eObjectType == BT_SMALLBLACK_DOWN || go->m_eObjectType == BT_BIGBLACK_DOWN)
									{
										if (!go->m_pParentGameObject) break;
										go = go->m_pParentGameObject;
									}
								}

								GameObject* nextObj = m_pObjectMatrix[row + 1][column];
								
								if (tap.y <= yLimitBottom - height / 2)
								{
									if (nextObj && go && (go->m_eObjectType == BT_RED_DOWN || go->m_eObjectType == BT_RED_LEFT
										|| go->m_eObjectType == BT_RED_RIGHT || go->m_eObjectType == BT_RED_UP) 
										&& (nextObj->m_eObjectType == BT_BLUE_UP))
									{
										// win 
										this->GoToScene();
										return;
									}

									if (go)
									{
										m_pObjectMatrix[row][column] = go->m_pAttachGameObject;
										if (go->m_pAttachGameObject)
										{
											go->m_pAttachGameObject->setPosition(currentX, currentY);
											go->m_pAttachGameObject->m_pParentGameObject = NULL;
										}
										go->m_pAttachGameObject = nextObj;

										if (nextObj)
											nextObj->m_pParentGameObject = go;
									}
									else
									{
										m_pObjectMatrix[row][column] = m_pPointer->m_pAttachGameObject;
										if (m_pPointer->m_pAttachGameObject)
										{
											m_pPointer->m_pAttachGameObject->setPosition(currentX, currentY);
											m_pPointer->m_pAttachGameObject->m_pParentGameObject = NULL;
										}
										m_pPointer->m_pAttachGameObject = nextObj;

										if (nextObj)
											nextObj->m_pParentGameObject = m_pPointer;
									}

									m_pPointer->setRow(row + 1);														
									m_pObjectMatrix[row + 1][column] = m_pPointer;
								}
							}
						}	
						else
						{
							tap.x = currentX;
							tap.y = currentY;
							m_pPointer->setTouch(NULL);
						}
					}							
				}
				else
				{
					tap.x = currentX;
					tap.y = currentY;

					m_pPointer->setTouch(NULL);
				}
																			
				Move(tap.x, tap.y, eMoveType);
			}
		}
	}
}

void PlayGameLayer::Move(float x, float y, MoveType_e eMoveType)
{
	m_pPointer->setPosition(x, y);
	GameObject* go = m_pPointer->m_pAttachGameObject;
	while (go)
	{		
		if (!go->m_pAttachGameObject) break;
		go = go->m_pAttachGameObject;
	}

	while (go)
	{
		if (eMoveType == MT_LEFT)
		{
			if (go->m_eObjectType != BT_BIGBLACK_LEFT && go->m_eObjectType != BT_SMALLBLACK_LEFT
				&& go->m_eObjectType != BT_RED_LEFT && go->m_eObjectType != BT_BLUE_LEFT)			
				go->setPosition(x, y);		
		}
		else if (eMoveType == MT_RIGHT)
		{
			if (go->m_eObjectType != BT_BIGBLACK_RIGHT && go->m_eObjectType != BT_SMALLBLACK_RIGHT
				&& go->m_eObjectType != BT_RED_RIGHT && go->m_eObjectType != BT_BLUE_RIGHT)
				go->setPosition(x, y);
		}
		else if (eMoveType == MT_UP)
		{
			if (go->m_eObjectType != BT_BIGBLACK_UP && go->m_eObjectType != BT_SMALLBLACK_UP
				&& go->m_eObjectType != BT_RED_UP && go->m_eObjectType != BT_BLUE_UP)
				go->setPosition(x, y);	
		}
		else if (eMoveType == MT_DOWN)
		{
			if (go->m_eObjectType != BT_BIGBLACK_DOWN && go->m_eObjectType != BT_SMALLBLACK_DOWN
				&& go->m_eObjectType != BT_RED_DOWN && go->m_eObjectType != BT_BLUE_DOWN)
				go->setPosition(x, y);					
		}
		go = go->m_pParentGameObject;	
	}
}

void PlayGameLayer::GoToScene()
{
	ShowWinnerScene *pScene = ShowWinnerScene::create();    
	CCDirector::sharedDirector()->replaceScene(pScene);
}